﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace CTThrottling.Common
{
    /// <summary>
    /// Web相关操作工具类
    /// </summary>
    public class WebHelper
    {
        //ip格式正则校验
        private static string _ipRegex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\."
                                         + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
                                         + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\."
                                         + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";

        /// <summary>
        ///  保留地址 min,max
        /// </summary>
        private static List<Tuple<long, long>> _backIp = new List<Tuple<long, long>>()
        {
            new Tuple<long, long>(167772161,184549374), //10.0.0.0/8
            new Tuple<long, long>(4294967295 ,4294967295),//255.255.255.255/32
            new Tuple<long, long>(2886729729 ,2887778302),//172.16.0.0/12
            new Tuple<long, long>(3232235521 ,3232301054),//192.168.0.0/16
            new Tuple<long, long>(1 ,16777214),//0.0.0.0/8
            new Tuple<long, long>(1681915905 ,1686110206),//100.64.0.0/10
            new Tuple<long, long>(2130706433 ,2147483646),//127.0.0.0/8
            new Tuple<long, long>(2851995649 ,2852061182),//169.254.0.0/16
            new Tuple<long, long>(3221225473 ,3221225726),//192.0.0.0/24
            new Tuple<long, long>(3221225985 ,3221226238),//192.0.2.0/24
            new Tuple<long, long>(3223307265 ,3223307518),//192.31.196.0/24
            new Tuple<long, long>(3224682753 ,3224683006),//192.52.193.0/24
            new Tuple<long, long>(3325256705 ,3325256958),//198.51.100.0/24
            new Tuple<long, long>(3405803777 ,3405804030),//203.0.113.0/24
            new Tuple<long, long>(4026531841 ,4294967294),//240.0.0.0/4
            new Tuple<long, long>(3232706561 ,3232706814)//192.175.48.0/24

        };


        /// <summary>
        /// 获取客户端Ip
        /// </summary>
        /// <param name="current"></param>
        /// <param name="filterBack">过滤保留地址</param>
        /// <returns></returns>
        public static string GetClientIp(System.Web.HttpContext current = null, bool filterBack = false)
        {
            if (current == null)
                current = System.Web.HttpContext.Current;

            if (current == null)
            {
                return "0.0.0.0";
            }

            string clientIp = string.Empty;
            try
            {
                if (current.Request.ServerVariables["HTTP_X_REAL_IP"] != null)
                {
                    clientIp = current.Request.ServerVariables["HTTP_X_REAL_IP"];
                    if (string.IsNullOrEmpty(clientIp))
                    {
                        clientIp = current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                    }
                }//nginx代理
                else if (current.Request.ServerVariables["HTTP_VIA"] != null)
                {
                    clientIp = current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                }//nginx代理
                else if (current.Request.Headers["X-Forwarded-For"] != null)
                {
                    clientIp = current.Request.Headers["X-Forwarded-For"];
                }

                if (!string.IsNullOrEmpty(clientIp))
                {
                    clientIp = GetRightIp(clientIp, filterBack);
                }
                //Net下用戶IP
                if (string.IsNullOrEmpty(clientIp))
                {
                    clientIp = current.Request.UserHostAddress;
                }

                clientIp = string.IsNullOrEmpty(clientIp) ? "0.0.0.0" : clientIp.Trim();

            }
            catch
            {
                clientIp = "0.0.0.0";
            }

            return clientIp;
        }


        /// <summary>
        /// 返回正确地址
        /// </summary>
        /// <param name="clientIp"></param>
        /// <param name="filterBack"></param>
        /// <returns></returns>
        public static string GetRightIp(string clientIp, bool filterBack)
        {
            try
            {
                var list = clientIp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                for (int i = list.Length - 1; i >= 0; i--)
                {
                    var ip = list[i].Trim();
                    if (!Regex.IsMatch(ip, _ipRegex))
                        continue;

                    if (!filterBack) return ip;

                    var longIp = IpHelper.IpToLong(ip);
                    //返回非保留地址
                    if (!_backIp.Exists(x => x.Item1 <= longIp && x.Item2 >= longIp))
                    {
                        return ip;
                    }
                }

                return "";
            }
            catch
            {
                return "";
            }
        }


    }
}
